package com.lobstar.xrpc.common.handler;

import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lobstar.xrpc.common.TaskExecutable;
import com.lobstar.xrpc.common.po.SMessage;
import com.lobstar.xrpc.common.po.Task;
import com.lobstar.xrpc.server.cache.TaskCache;
import com.lobstar.xrpc.server.handler.task.TaskCallback;
import com.lobstar.xrpc.server.listener.DefaultServiceListener;
import com.lobstar.xrpc.service.base.ServiceInvoker;
import com.lobstar.xrpc.service.utils.JsonUtils;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.concurrent.Future;

public abstract class ServiceHandler extends SimpleChannelInboundHandler<SMessage>{
	protected static final Logger LOGGER = LoggerFactory.getLogger(ServiceHandler.class);

	protected static final String TAG_EXCEPTION = "_exception";
	protected static final String TAG_RESPONSE = "_ret";

	protected TaskExecutable taskExecutable;

	public ServiceHandler(TaskExecutable taskExecutable) {
		this.taskExecutable = taskExecutable;
	}

	protected void handleHeartbeat(ChannelHandlerContext ctx, SMessage msg) {}
	protected void handleInit(ChannelHandlerContext ctx, SMessage msg) {}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, SMessage msg) throws Exception {
		switch (msg.getType()) {
		case INIT:
			//LOGGER.info("init channel");
			handleInit(ctx,msg);
			break;
		case HEART:
			handleHeartbeat(ctx,msg);
			break;
		case REQUEST:
			//LOGGER.info("service request:{}",msg.getMethod());
			handleRequest(ctx,msg);
			//写返回值,注入requestId
			break;
		case RESPONSE:
			//根据id将结果注入response
			//LOGGER.info("get service response");
			handleResponse(ctx,msg);
			break;
		default:
			break;
		}
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		super.channelInactive(ctx);
	}
	protected void handleRequest(ChannelHandlerContext ctx,SMessage msg) {
		taskExecutable.getTaskProcessor().execute(()->{
			Object ret = null;
			Object ex = null;
			ServiceInvoker invoker = taskExecutable.getInvoker();
			//记录msg的id标识返回对象
			try {
				if(invoker.hasMethod(msg)) {
					try {
						ret = invoker.invoke(msg);
						msg.addAttribute(TAG_RESPONSE, JsonUtils.toJson(ret));
					}catch(Exception e) {
						if(e.getClass() == InvocationTargetException.class) {
							ex = ((InvocationTargetException)e).getTargetException().toString();
						}else {
							ex = e.toString();
						}
					}
				}else {
					ex = "no method";
				}
				if(ex != null) {
					msg.addAttribute(TAG_EXCEPTION, ex);
				}
				ctx.channel().writeAndFlush(msg.buildResponse());
			}catch(Exception e) {
				LOGGER.error("request",e);
				throw e;
			}
		});
	}
	protected void handleResponse(ChannelHandlerContext ctx, SMessage message) {
		String id = message.getId();
		Task task = taskExecutable.getResponseHandler().get(id);
		if(task != null) {
			TaskCallback callback = task.getCallback();
			if(message.getParams().containsKey(TAG_EXCEPTION)) {
				if(callback != null) {
					callback.handleException(message.getParams().get(TAG_EXCEPTION).toString());
				}
			}else
			if(message.getParams().containsKey(TAG_RESPONSE)) {
				String ret = message.getParams().get(TAG_RESPONSE).toString();
				if(callback != null) {
					callback.callback(ret);
				}
			}else {
				if(callback != null) {
					callback.callback(null);
				}
			}
		}
	}
}
